﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Xna.Framework.Content;
using System.Collections.Generic;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;
using System.IO.IsolatedStorage;
using LastStand.gameContent.Friendlies;
using LastStand.gameContent.enemies;

/*
 * GameCore holds the enumeration GameState, as well as the objects
 * the the game logic will interact with.
 */

namespace LastStand.gameContent
{
	public class GameCore
	{
		//the player's save, if any.
		private IsolatedStorageFile playerSave;

		/// <summary>
		/// GameState determines what will be happening on the screen. The conditions are
		/// in this GameCore's update method.
		/// 
		/// PLAYING: If player has a save, it will be read into the game and the game will
		///				appear as a new day on their last saved day, if any.
		///				Player input is polled and GameTimer is active, game logic running.
		///				
		/// PAUSED: GameTimer is paused and game logic halts. 
		///				Player input is no longer polled except for pressing Resume or Quit.
		///				
		/// END_DAY: GameTimer ends and paused. Player's score is determined and displayed.
		///				Game saved and player given option to purchase items/upgrades,
		///				Go on to the next day, or Quit with their game saved. When they play
		///				Next time, their game will begin as a new day at their last saved point.
		///				
		/// GAME_OVER: GameTimer ends, Player no longer being polled for input. Death animations
		///				played, Game over text. player's scores are totaled and saved to
		///				their save. Option to return to Play again or go to main menu.
		/// </summary>
		public enum GameState
		{
			PLAYING,
			PAUSED,
			END_DAY,
			GAME_OVER
		}

        public GameState gameState;

        //games grid
        public Grid grid;

		//the player.
		public Player player;

        //enemy and friendly lists for drawing
        public List<Sprite> spriteList;
        public List<Sprite> enemyList;
        public List<Shot> shotList;

        //control over the players view.
        public ViewControl view;

        //control day events
        public DayHandler day;

        //control for the structure building UI
        public Build build;

        //all textures to be loaded
        Texture2D TestDay;
		Texture2D meleeAttacker;
        Texture2D riflemanTexture;
        Texture2D shotTexture;

        TextBlock diag = new TextBlock();

		//the Game's "AI" controller. It runs the course of the game for the player to react.
		//DayController director;

		//the name of the game's save file, stored in the titlelocation
		private string saveFile = "saveFile.txt";

		/// <summary>
		/// Constructor initializes the gamecore class and determines what state we will begin at.
		/// </summary>
		/// <param name="content">Content manager to be used for loading textures</param>
		/// <param name="texFiles">string of texture file names to be loaded with contentmanager</param>
		public GameCore(Grid grid)
		{
            //set a grid for the whole GameCore
            this.grid = grid;

            //GameState will always start out as paused at the start of every game
            gameState = GameState.PLAYING;

			//get storage state...
			playerSave = IsolatedStorageFile.GetUserStoreForApplication();

            //init spritelist
            spriteList = new List<Sprite>();
            enemyList = new List<Sprite>();
            shotList = new List<Shot>();

			//...then check if the player has a save...
            if (playerSave.FileExists(saveFile))
            {
                loadSave(saveFile);
            }

            //no save found. Start at beginning.
            else
            {
                player = new Player(new Vector2(625, 200));
            }

            //actually load the day handler
            day = new DayHandler();

            //TO REMOVE:
            //
            //Diagnosis text block creation
            diag.SetValue(Canvas.HorizontalAlignmentProperty, HorizontalAlignment.Left);
            diag.SetValue(Canvas.VerticalAlignmentProperty, VerticalAlignment.Top);
            diag.SetValue(Canvas.MarginProperty, new Thickness(0,0,0,0));
			diag.Foreground = new SolidColorBrush(System.Windows.Media.Colors.Black);
            //adding diag text to the main grid
            grid.Children.Add(diag);
        }

        /// <summary>
        /// draws all content for the game
        /// </summary>
        public void Draw(SpriteBatch sb)
        {
            build.Draw(sb);
			//checks which state we're in and draws accordingly
			switch (gameState)
			{
				case GameState.PLAYING:
					{


						foreach (Sprite sprite in spriteList)
						{
							sprite.Draw(sb);
						}
                        foreach (Shot shot in shotList)
                        {
                            shot.Draw(sb);
                        }
                        foreach (Sprite enemy in enemyList)
                        {
                            enemy.Draw(sb);
                        }

						break;
					}
				case GameState.PAUSED:
					{
						//draws the day number
						day.Draw(sb);
						break;
					}
				case GameState.END_DAY:
					{
						//draws the view
						//includes the game background
						//and the movement of all other objects
						
						break;
					}

				case GameState.GAME_OVER:
					{
						break;
					}
			}

            //draw the day
           // day.Draw(sb);

            //draw the building phase
           // build.Draw(sb);              //TODO: Make only drawable at night
        }

        /// <summary>
        /// updates all content for the game
        /// </summary>
        /// <param name="timer"></param>
        public void Update(GameTimerEventArgs timer)
        {

			//checks which state we're in and draws accordingly
			switch (gameState)
			{
				case GameState.PLAYING:
					{
                        build.Update(timer, spriteList);
                        build.BuildMenu.Visibility = Visibility.Visible;
						foreach (Sprite sprite in spriteList)
						{
							sprite.Update(timer);
						}
                        foreach (Shot shot in shotList)
                        {
                            shot.Update(timer);
                        }
                        foreach (Sprite enemy in enemyList)
                        {
                            enemy.Update(timer);
                        }

						break;
					}
				case GameState.PAUSED:
					{
						//draws the day number
						day.Update(timer);
						break;
					}
				case GameState.END_DAY:
					{
						//draws the view
						//includes the game background
						//and the movement of all other objects

						//at night, update build
						build.isVis = true;

						break;
					}

				case GameState.GAME_OVER:
					{
						break;
					}
			}
            //move

            grid.UpdateLayout();
        }

		//loads the content of the game; textures and sounds.
		public void LoadContent(ContentManager content)
		{
            //create the build class
            build = new Build(grid, spriteList, view, content);

            //pairs texture variables with their matching image (.png) file

			meleeAttacker = content.Load<Texture2D>("meleeAttacker");
            riflemanTexture = content.Load<Texture2D>("rifleman");
            shotTexture = content.Load<Texture2D>("shot");
            
            //load the textures needed for handeling days
            day.Load(content);



			//enemyList.Add(new meleeAttacker(new Vector2(800f, 200f), meleeAttacker));
            enemyList.Add(new meleeAttacker(new Vector2(700f, 100f), meleeAttacker));
            enemyList.Add(new meleeAttacker(new Vector2(300f, 300f), meleeAttacker));
            spriteList.Add(new Rifleman(new Vector2(400f, 100f), riflemanTexture, enemyList, shotList, shotTexture));
            
            //load all construction textures
            build.Load(content);
		}

		//loads the player's save and apply values.
		/*
				 * file save format:
				 * //Player information
				 * day number player is on
				 * 
				 * Number of rifletowers
				 * //FOR EACH RIFLETOWER (Seperated by spaces):
				 * //Ex: 1 100 4
				 *		 2 150 6
				 *		 1  75 0
				 *		 
				 * current level, current health, current number of riflemen
				 * //end file
				 */
		private void loadSave(string save)
		{
			//create a char buffer so we can figure out whats in the file/
			//note to self: don't fuckin allow file's lines to get that goddamn long.
			char[] lineBuffer;
			string lineBufferStr;

			//open the stream of the save file
			System.IO.Stream stream = TitleContainer.OpenStream(save);

			//create a stream reader for the stream for the file.
			System.IO.StreamReader sreader = new System.IO.StreamReader(stream);

			//reads and processes each line until we're at the end of the file.
			//sreader.ReadLine() reads the line and skips to the next line
			//and it is ready to read the next bit of information.
			while (!sreader.EndOfStream)
			{
				//player info
				int playerLevel;

				//tower info
				int numTowers;
				int currentHealth;

				//send into our char array. responsible for
				//continuing to each "#_" marker.
				lineBuffer = sreader.ReadLine().ToCharArray();

				//and copy to a string to keep track of our switch
				lineBufferStr = lineBuffer.ToString();

				switch (lineBufferStr)
				{
					case "#p":
						//read the next line, which is player level.
						lineBuffer = sreader.ReadLine().ToCharArray();

						//get the player level from the line buffer
						playerLevel = Convert.ToInt16(lineBuffer);

						//create the new player and set their day level.
						player = new Player(new Vector2(625, 200));
						player.DayLevel = playerLevel;

						break;

					case "#s":
						//read number of structures
						lineBuffer = sreader.ReadLine().ToCharArray();

					break;

				}



				lineBuffer = sreader.ReadLine().ToCharArray();

			}
		}
	}
}
